#pragma once

#include "avl.h"
#include "hashtable.h"

/**
 * @brief 有序集合结构，同时使用AVL树和哈希表索引
 */
struct ZSet 
{
    AVLNode *root = NULL;   ///< AVL树根节点，按(score, name)排序
    HMap hmap;              ///< 哈希表，按name索引
};

/**
 * @brief 有序集合节点结构
 */
struct ZNode 
{
    AVLNode tree;           ///< AVL树节点
    HNode   hmap;           ///< 哈希表节点
    double  score = 0;      ///< 分数
    size_t  len = 0;        ///< 名称长度
    char    name[0];        ///< 柔性数组，存储名称
};

/**
 * @brief 向有序集合中插入元素
 * @param zset 有序集合指针
 * @param name 元素名称
 * @param len 名称长度
 * @param score 分数
 * @return 如果是新插入返回true，更新已有元素返回false
 */
bool zset_insert(ZSet *zset, const char *name, size_t len, double score);

/**
 * @brief 向有序集合中添加元素（别名）
 * @param zset 有序集合指针
 * @param name 元素名称
 * @param len 名称长度
 * @param score 分数
 * @return 如果是新插入返回true，更新已有元素返回false
 */
bool zset_add(ZSet *zset, const char *name, size_t len, double score);

/**
 * @brief 初始化有序集合
 * @param zset 有序集合指针
 */
void zset_new(ZSet *zset);

/**
 * @brief 从有序集合中删除并返回元素
 * @param zset 有序集合指针
 * @param name 元素名称
 * @param len 名称长度
 * @return 删除的节点指针，未找到返回NULL
 */
ZNode *zset_pop(ZSet *zset, const char *name, size_t len);

/**
 * @brief 删除有序集合节点
 * @param node 要删除的节点
 */
void znode_del(ZNode *node);

/**
 * @brief 查询有序集合中大于等于指定(score, name)的元素
 * @param zset 有序集合指针
 * @param score 分数
 * @param name 名称
 * @param len 名称长度
 * @return 找到的节点指针，未找到返回NULL
 */
ZNode *zset_query(ZSet *zset, double score, const char *name, size_t len);

/**
 * @brief 销毁有序集合
 * @param zset 有序集合指针
 */
void zset_dispose(ZSet *zset);

/**
 * @brief 在有序集合中查找元素
 * @param zset 有序集合指针
 * @param name 元素名称
 * @param len 名称长度
 * @return 找到的节点指针，未找到返回NULL
 */
ZNode *zset_lookup(ZSet *zset, const char *name, size_t len);

/**
 * @brief 从有序集合中删除元素
 * @param zset 有序集合指针
 * @param node 要删除的节点
 */
void zset_delete(ZSet *zset, ZNode *node);

/**
 * @brief 查找第一个大于等于指定(score, name)的元素
 * @param zset 有序集合指针
 * @param score 分数
 * @param name 名称
 * @param len 名称长度
 * @return 找到的节点指针，未找到返回NULL
 */
ZNode *zset_seekge(ZSet *zset, double score, const char *name, size_t len);

/**
 * @brief 清空有序集合
 * @param zset 有序集合指针
 */
void zset_clear(ZSet *zset);

/**
 * @brief 按偏移量查找有序集合中的节点
 * @param node 起始节点
 * @param offset 偏移量
 * @return 目标节点指针，未找到返回NULL
 */
ZNode *znode_offset(ZNode *node, int64_t offset); 